/**
 * 
 */
package de.androidbuch.amando.providers;

import java.io.FileNotFoundException;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
import android.util.Log;
import de.androidbuch.amando.AmandoDatenbank;
import de.androidbuch.amando.fotos.db.PositionsFotoColumns;
import de.androidbuch.amando.fotos.db.PositionsFotoTbl;

/**
 * Dieser Content Provider liefert eine Übersicht aller zu
 * einem Geokontakt gespeicherten Fotos zu einer Route. <br>
 * Die Routen werden über einen vom Autor vergebenen Namen
 * eindeutig identifiziert.
 * <p>
 * Dieser Name dient als Schlüssel für den Zugriff auf die
 * Liste der Fotos dieser Route. Im Anschluss kann das Foto
 * als Stream abgerufen werden.
 * <p>
 * Der Provider erlaubt das Einfügen und die Löschung eines
 * Fotos. Änderungsoperationen sind nicht erlaubt.
 * 
 * @author pant
 */
public class FotoProvider extends ContentProvider {
  /** Markierung für Logging. */
  private static final String TAG = "RoutenBilderProvider";

  /**
   * Eindeutige Kennung (AUTHORITY) für diesen Provider.
   */
  public static final String AUTHORITY =
      "de.androidbuch.amando.fotoprovider";

  /**
   * Basis-URI des Providers.
   */
  public static final Uri AUTHORITY_URI =
      Uri.parse("content://" + AUTHORITY);

  /**
   * Uri-Zähler für das Fotoverzeichnis.
   */
  private static final int FOTO_VERZ = 1;
  /**
   * Uri-Zähler für einzelnes Foto.
   */
  private static final int FOTO_ID = 2;

  /**
   * Wandelt URIs in numerische Werte um, damit sie für
   * Fallunterscheidungen genutzt werden können.
   */
  private static final UriMatcher URI_MATCHER;

  static {
    URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    URI_MATCHER.addURI(AUTHORITY,
        FotoVerzeichnis.CONTENT_PATH, FOTO_VERZ);
    URI_MATCHER.addURI(AUTHORITY,
        FotoVerzeichnis.CONTENT_PATH + "/#", FOTO_ID);
  }

  /** Referenz auf die zugrundeliegende Datenbank. */
  private AmandoDatenbank mDb;
  
  /**
   * Repräsentiert die Datenmenge des Fotoverzeichnisses. 
   * <br>
   * Es sind alle Konstanten und Attributnamen enthalten,
   * die für den Zugriff auf diese Datenmenge des Content
   * Providers benötigt werden. <br>
   * Um den Zusammenhang zwischen Content Provider und
   * Datenbank zu verdeutlichen, werden die Attributnamen
   * der Tabellenspalten hier nochmal explizit erwähnt. <br>
   * Falls der Provider <strong>alle</strong> Attribute der
   * Tabelle herausgeben würde, könnte das
   * <code>FotoVerzeichnis</code> auch
   * <code>PositionsFotoColumns</code> implementieren.
   */
  public static final class FotoVerzeichnis
      implements BaseColumns, PositionsFotoColumns {

    /**
     * Pfadname zur Ergänzung der Basis-Uri des Content
     * Providers. 
     * Der Pfad verweist auf die vorliegende Datenmenge.
     */
    public static final String CONTENT_PATH = "fotos";
    
    /**
     * Basis-URI für das FotoVerzeichnis.
     */
    public static final Uri CONTENT_URI =
      Uri.withAppendedPath(
          FotoProvider.AUTHORITY_URI, CONTENT_PATH);

    /**
     * Mime type des Verzeichnisses.
     */
    public static final String CONTENT_TYPE = 
      "vnd.android.cursor.dir/vnd.amando.fotodaten";

    /**
     * Mime type eines Foto-Verzeichniseintrags.
     */
    public static final String CONTENT_ITEM_TYPE = 
      "vnd.android.cursor.item/vnd.amando.fotodaten";

    /**
     * Liste der Spalten, die vom RoutenBilderProvider
     * immer zurückgeliefert werden.
     */
    public static final String[] ALL_COLUMNS = 
      new String[] {
      _ID,
      TITEL,
      STICHWORT_POS,
      DATEINAME
    };
    
    /**
     * Sortierreihenfolge, falls keine andere angegeben
     * wird.<br>
     * Standardmäßig wird nach Bildtitel sortiert.
     */
    public static final String DEFAULT_SORT_ORDER = 
      TITEL + " ASC";

    /**
     * Statische Klasse.
     */
    private FotoVerzeichnis() {
    }
  }

  @Override
  public boolean onCreate() {
    Log.i(TAG, "RoutenBilderProvider aktiv.");
    mDb = new AmandoDatenbank(getContext());
    return true;
  }

  
  @Override
  public String getType(Uri uri) {
    switch (URI_MATCHER.match(uri)) {
    case FOTO_VERZ:
      return FotoVerzeichnis.CONTENT_TYPE;

    case FOTO_ID:
      return FotoVerzeichnis.CONTENT_ITEM_TYPE;

    default:
      throw new IllegalArgumentException(
          "Unbekannte URI " + uri);
    }
  }
  
  @Override
  public Uri insert(Uri uri, ContentValues values) {
    if (URI_MATCHER.match(uri) != FOTO_VERZ) {
      throw new IllegalArgumentException(
          "Einfuegen für diese URI nicht erlaubt!");
    }
    
    final SQLiteDatabase dbCon = 
      mDb.getWritableDatabase();
    dbCon.beginTransaction();
    try {
      final long id =
        dbCon.insertOrThrow(
            PositionsFotoTbl.TABLE_NAME, null,
          values);
      Log.i(TAG,
          "Foto mit id=" + id + " erzeugt.");

      final Uri neuesFotoUri = ContentUris.withAppendedId(
          FotoVerzeichnis.CONTENT_URI, 
          id);
      getContext().getContentResolver().notifyChange(
          neuesFotoUri, null);
      dbCon.setTransactionSuccessful();
      return neuesFotoUri;
    } finally {
      dbCon.endTransaction();
      dbCon.close();
    }
  }

  @Override
  public int delete(Uri uri, String selection,
      String[] selectionArgs) {
    final SQLiteDatabase dbCon = 
      mDb.getWritableDatabase();
    
    int anzahlLoeschungen = 0;
    try {
      switch (URI_MATCHER.match(uri)) {
        case FOTO_VERZ:
          anzahlLoeschungen =
              dbCon.delete(
              PositionsFotoTbl.TABLE_NAME,
              selection, selectionArgs);
          break;
        case FOTO_ID:
          anzahlLoeschungen =
              dbCon.delete(
              PositionsFotoTbl.TABLE_NAME,
              PositionsFotoTbl.WHERE_ID_EQUALS,
              new String[] {
              uri.getPathSegments().get(1)
              });
          break;
        default:
          throw new IllegalArgumentException(
              "Unbekannte URI " + uri);
      }
    } finally {
      dbCon.close();
    }

    if (anzahlLoeschungen > 0) {
      getContext().getContentResolver().notifyChange(
          uri, null);
    }
    return anzahlLoeschungen;
  }


  @Override
  public Cursor query(Uri uri, String[] projection,
      String selection, String[] selectionArgs,
      String sortOrder) {
    final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(PositionsFotoTbl.TABLE_NAME);

//    try {
//      Thread.sleep(5000);
//    } catch (InterruptedException e) {
//    }
    switch (URI_MATCHER.match(uri)) {
      case FOTO_VERZ:
        if (sortOrder == null) {
          // CHECKSTYLE:OFF - null-sortierung ueberschrieben
          sortOrder = FotoVerzeichnis.DEFAULT_SORT_ORDER;
          // CHECKSTYLE:ON
        }
        break;
      case FOTO_ID:
        qb.appendWhere(PositionsFotoTbl.ID
            + "=" + uri.getPathSegments().get(1));
        break;

      default:
        throw new IllegalArgumentException(
            "Unbekannte URI " + uri);
    }

    final SQLiteDatabase dbCon =
        mDb.getReadableDatabase();
    return qb.query(
        dbCon,
        FotoVerzeichnis.ALL_COLUMNS,
        selection,
        selectionArgs, null, null, sortOrder);
  }

  /**
   * Wird vom Content Provider nicht unterstützt.
   */
  // CHECKSTYLE:OFF - javadoc nicht nötig
  public int update(Uri uri, ContentValues values,
      String selection, String[] selectionArgs) {
    throw new UnsupportedOperationException();
  }
  // CHECKSTYLE:ON

  @Override
  public ParcelFileDescriptor openFile(Uri uri, String mode)
      throws FileNotFoundException {
    if (URI_MATCHER.match(uri) != FOTO_ID) {
      throw new IllegalArgumentException(
          "Operation nur für Einzeldatei erlaubt.");
    }
    return openFileHelper(uri, mode);
  }

}
